package cn.itcast.config;

import com.mongodb.*;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDbFactory;
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
import org.springframework.data.mongodb.core.convert.*;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;

import java.util.ArrayList;
import java.util.List;


/**
 * Description: mongo配置
 */
@Configuration
public class MongoConfig {


    // 注入配置实体
    @Autowired
    private MongoPropertiesEntity mongoPropertiesEntity;

    @Bean
    @ConfigurationProperties(prefix = "spring.data.mongodb")
    MongoPropertiesEntity mongoSettingsProperties() {
        return new MongoPropertiesEntity();
    }

    /**
     * 覆盖默认的MongoDbFactory
     */
    @Bean
    MongoDbFactory mongoDbFactory() {
        //客户端配置（连接数、副本集群验证）
        MongoClientOptions.Builder builder = new MongoClientOptions.Builder();
        builder.connectionsPerHost(mongoPropertiesEntity.getConnectionsPerHost());
        //builder.minConnectionsPerHost(mongoSettingsProperties.getMinConnectionsPerHost()s);
        if (mongoPropertiesEntity.getReplicaSet() != null) {
            builder.requiredReplicaSetName(mongoPropertiesEntity.getReplicaSet());
        }
        builder.readPreference(ReadPreference.secondary());
        MongoClientOptions mongoClientOptions = builder.build();

        // MongoDB地址列表
        List<ServerAddress> serverAddresses = new ArrayList<>();
        for (String host : mongoPropertiesEntity.getHosts()) {
            Integer index = mongoPropertiesEntity.getHosts().indexOf(host);
            Integer port = mongoPropertiesEntity.getPorts().get(index);
            serverAddresses.add(new ServerAddress(host, port));
        }

        // 连接认证
        List<MongoCredential> mongoCredentialList = new ArrayList<>();
        if (mongoPropertiesEntity.getUsername() != null) {
            mongoCredentialList.add(MongoCredential.createScramSha1Credential(mongoPropertiesEntity.getUsername(), mongoPropertiesEntity.getAuthenticationDatabase() != null ? mongoPropertiesEntity.getAuthenticationDatabase() : mongoPropertiesEntity.getDatabase(), mongoPropertiesEntity.getPassword().toCharArray()));
        }

        //创建客户端和Factory
        MongoClient mongoClient = new MongoClient(serverAddresses, mongoCredentialList, mongoClientOptions);
        MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongoClient, mongoPropertiesEntity.getDatabase());

        return mongoDbFactory;
    }

    /**
     * 保存时, 过滤掉class全路径
     *
     * @param factory
     * @param context
     * @param beanFactory
     * @return
     */
    @Bean
    public MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context, BeanFactory beanFactory) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
        try {
            mappingConverter.setCustomConversions(beanFactory.getBean(CustomConversions.class));
        } catch (NoSuchBeanDefinitionException ignore) {
        }
        // Don't save _class to mongo
        mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
        mappingConverter.setMapKeyDotReplacement("。");
        return mappingConverter;
    }
}